#pragma once
#include "Common.hpp"
#include <jsoncpp/json/json.h>
#include "Socket.hpp"
#include "InterAddr.hpp"
#include<functional>

class Request
{
    public:
   Request() {}
    Request(int x, int y, char oper)
        : _x(x),
          _y(y),
          _oper(oper)
    {
    }

    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }
    ~Request() {}

private:
    int _x;
    int _y;
    char _oper;
};
class Response
{
    public:
    Response() {}
    Response(int result, int code)
        : _result(result),
          _code(code)
    {
    }
    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
      void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    ~Response() {}

private:
    int _result;
    int _code;
};

const std::string sep = "\r\n";
using func_t = std::function<Response (Request &req)>;
class Protocol
{
    public:

    std::string Encode(const std::string &jsonstr)
    {
        // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
        std::string len = std::to_string(jsonstr.size());
        return sep + len + jsonstr + sep;
    }
    // 50\r\n{"x": 10, "y
    // 50\r\n{"x": 10, "y" : 20, "oper" :
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n

    bool Decode(std::string &buffer, std::string *package)
    {
        // 先要找到最前面的sep
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
            return false;
        // 走到这里说明至少读到了50\r\n
        std::string package_len_str = buffer.substr(0, pos);
        int package_len = std::stoi(package_len_str);
        int total_len = sep.size()* 2 + package_len;
        // 至少有这个 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
        if (buffer.size() < total_len)
            return false;
        *package = buffer.substr(pos + sizeof(sep), package_len);
        buffer.erase(0, total_len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string buffer_queue;
        while (1)
        {
            int n = sock->Recv(&buffer_queue);
            if (n > 0)
            { std::string json_package;
                // 1. 解析报文，提取完整的json请求，如果不完整，就让服务器继续读取
                bool ret = Decode(buffer_queue, &json_package);
                if(!ret)
                    continue;
                // 我敢100%保证，我一定拿到了一个完整的报文
                // {"x": 10, "y" : 20, "oper" : '+'} -> 你能处理吗？
                // 2. 请求json串，反序列化
                Request req;
                bool ok = req.Deserialize(json_package);
                if(!ok)
                    continue;
                // 3. 我一定得到了一个内部属性已经被设置了的req了.
                // 通过req->resp, 不就是要完成计算功能嘛！！业务
                Response resp = _func(req);
                
                // 4. 序列化
                std::string json_str = resp.Serialize();

                // 5. 添加自定义长度
                std::string send_str = Encode(json_str); // 携带长度的应答报文了"len\r\n{result:XXX, code:XX}\r\n"

                // 6. 直接发送
                sock->Send(send_str);

               
 
                
            }else 
            if(n==0)
            {
                printf("client quit\n");
                break;
            }else
            {
                perror("fail");
                break;
            }
        }
    }

private:
func_t _func;
};
